package com.yusp75.myexam.ui.display

import android.annotation.SuppressLint
import android.content.res.Resources
import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
import android.widget.EditText
import android.widget.RadioButton
import android.widget.RadioGroup
import android.widget.SeekBar
import android.widget.TextView
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs
import com.google.android.material.snackbar.Snackbar
import com.yusp75.myexam.R
import com.yusp75.myexam.data.Question
import com.yusp75.myexam.data.QuestionBounds
import com.yusp75.myexam.databinding.FragmentDisplayBinding
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.launch
import org.koin.androidx.viewmodel.ext.android.viewModel

class DisplayFragment : Fragment() {

    private var _binding: FragmentDisplayBinding? = null
    private val binding get() = _binding!!
    private val viewModel: DisplayViewModel by viewModel()

    private var makeChoice = false
    private var isExercise = true

    // 选择项部分
    private var selectedOption: Int = -1  // 选项变量
    private val OPTION_PADDING_DP = 16
    private val radioButtons: MutableList<RadioButton> = mutableListOf()

    // 边界
    private var _bounds: QuestionBounds? = null

    // 进度条值
    private var lastProgress = -1

    @SuppressLint("SetTextI18n")
    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {

        _binding = FragmentDisplayBinding.inflate(inflater, container, false)
        val root: View = binding.root

        val timeDisplay: TextView = binding.timeDisplay
        viewModel.timeElapsed.observe(viewLifecycleOwner) { time ->
            timeDisplay.text = "%05.1fs".format(time / 1000.0)
        }
        // 参数： 考试，练习
        val args: DisplayFragmentArgs by navArgs()
        isExercise = when (args.btnPressed) {
            "练习" -> true
            "考试" -> false
            else -> false // 默认值
        }

        // 在Activity/Fragment的UI层收集StateFlow
        lifecycleScope.launch {
            repeatOnLifecycle(Lifecycle.State.STARTED) {
                viewModel.currentQuestion.collect { question ->
                    question?.let {
                        binding.questionAnswer.text = it.answer
                        binding.questionAnalysis.text = it.analysis
                    }
                }
            }
        }

        // 隐藏seekbar
        if (!isExercise) {
            binding.progressText.visibility = View.GONE
            binding.seekBar.visibility = View.GONE
        }
        if (isExercise) {
            binding.questionProgress.visibility = View.GONE
        }

        // 选项选择
        binding.rgAnswer.setOnCheckedChangeListener { group, checkedId ->
            makeChoice = true // 做了选择
            // 计时
            val elapsedTime = viewModel.stopTimer()
            binding.timeDisplay.text = "%05.1fs".format(elapsedTime / 1000.0)

            group.findViewById<RadioButton>(checkedId).text?.toString().orEmpty()
                .let { selectedText ->
                    viewModel.currentQuestion.value?.takeIf {
                        !viewModel.checkAnswer(selectedText) && isExercise
                    }?.run {
                        binding.run {
                            questionAnswer.visibility = View.VISIBLE
                            // 无解析则不显示
                            viewModel.currentQuestion.value?.analysis?.takeIf { it.isNotEmpty() }
                                ?.let {
                                    questionAnalysis.visibility = View.VISIBLE
                                }
                        }
                    }
                }
        }

        // 按钮：提示
        binding.btnHint.apply {
            visibility = if (isExercise) View.VISIBLE else View.GONE
            setOnClickListener {
                isExercise.takeIf { it }?.let {
                    with(binding) {
                        questionAnswer.visibility = View.VISIBLE
                        questionAnalysis.visibility = View.VISIBLE
                    }
                }
            }
        }

        // 按钮：提交
        val buttonNext = binding.btnNextQuestion
        buttonNext.setOnClickListener {
            // 优化说明：使用takeUnless+let处理false情况，run处理else分支，setAction支持lambda表达式
            makeChoice.takeUnless { it }?.let {
                Snackbar.make(
                    requireActivity().window.decorView,
                    "请做一个选择",
                    Snackbar.LENGTH_SHORT
                )
                    .setAction("Action") { }
                    .show()
            } ?: run {
                viewModel.recordFailure()
                // 清空
                makeChoice = false
                with(binding) {
                    questionAnswer.visibility = View.INVISIBLE
                    questionAnalysis.visibility = View.INVISIBLE
                }
                // 考试时记录错题

                // 下一题
                getOneQuestion()
            }

        }

        // 跳转fragment
        viewModel.isCompleted.observe(viewLifecycleOwner) { it ->
            it.takeIf { it }?.let { findNavController().navigate(R.id.nav_result) }
        }

        //
        return root
    }

    @SuppressLint("SetTextI18n")
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        // 题目边界
        lifecycleScope.launch {
            repeatOnLifecycle(Lifecycle.State.STARTED) {
                viewModel.questionBounds.collect { bounds ->
                    bounds?.let {
                        // 当bounds不为null时的处理逻辑
                        _bounds = bounds
                        // 进度条值范围
                        binding.seekBar.apply {
                            max = _bounds!!.max
                            min = _bounds!!.min
                        }
                        Log.d("QuestionBounds", "获取到bounds: $it")
                    }
                }
            }
        }

        // 初始化进度条监听
        viewModel.lastId.observe(viewLifecycleOwner) {
            binding.apply {
                seekBar.progress = it
                progressText.text = indicatorOfSeekBar(it)
            }
        }

        binding.seekBar.onProgressChangedWithCallback(
            onProgressChanged =
                { progress ->
                    binding.progressText.text = indicatorOfSeekBar(progress)
                    viewModel.emitProgress(progress)
                },
            onProgressEnd =
                { viewModel.emitProgress(it) }
        )

        // 做题进度
        lifecycleScope.launch {
            viewModel.currentIndex.collect { value ->
                binding.questionProgress.text =
                    "总数：${viewModel.questionNumOfPaper}，当前：${value + 1}"
            }
        }

        // 复位
        viewModel.reset()
        // 第1次需要取题
        getOneQuestion()

        //
    }

    // 进度条指示
    private fun indicatorOfSeekBar(progress: Int): String {
        return progress.toString() + "/" + _bounds?.max
    }

    // 取1个题
    private fun getOneQuestion() {
        if (!viewModel.moveToNext()) {
            viewLifecycleOwner.lifecycleScope.launch {
                viewModel.loadNextPage(viewModel.currentBookId, isExercise)
            }
        }

        updateUI()  // 更新UI
    }

    private fun updateUI() {
        viewLifecycleOwner.lifecycleScope.launch {
            try {
                viewModel.currentQuestion
                    .filterNotNull()
                    .collect { question ->
                        with(binding) {
                            btnNextQuestion.isEnabled = true
                            // clear
                            rgAnswer.removeAllViews()
                            options.removeAllViews()

                            val options = when (question.questionType) {
                                "选择" -> handleChoiceQuestion(question)
                                "判断" -> handleJudgeQuestion(question)
                                else -> emptyList<String>().also {   // 默认
                                    Log.w(
                                        "题目",
                                        "不支持题目类型格式: ${question.questionType}"
                                    )
                                }
                            }
                            renderOptionsButton(options)
                            viewModel.startTimer()
                        }
                    }
            } catch (e: Exception) {
                handleQuestionError(e)
            }
        }
    }


    override fun onPause() {
        super.onPause()
        viewModel.saveState()
    }

    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }

    // 正则提取选项
    private fun extractOptions(input: String): Pair<String, List<String>>? {
        val pattern = Regex("""(?s)(.*?)((?:[A-Z]、[^\n]*(?:\n|$))+)""")
        val matchResult = pattern.find(input) ?: return null

        val (questionStem, optionsBlock) = matchResult.destructured
        val optionsList = optionsBlock.trim().split("\n").filter { it.isNotBlank() }

        return questionStem.trim() to optionsList
    }

    // 添加选项textview
    private fun addOptions(options: List<String>): List<String> {
        binding.options.apply {
            // removeAllViews()
            options.forEachIndexed { index, text ->
                addOptionView(index, text)
            }
        }
        return options.map { it.firstOrNull()?.toString() ?: "" }
    }

    private fun ViewGroup.addOptionView(index: Int, text: String) {
        val context = context // 直接使用ViewGroup的context
        TextView(context).apply {
            // 样式设置
            setTextAppearance(R.style.OptionTextStyle)
            this.text = text
            // 布局参数
            val padding = OPTION_PADDING_DP.dpToPx()
            setPadding(padding, padding, padding, padding)
            // 背景状态管理
            background = ContextCompat.getDrawable(context, R.drawable.option_default_bg)

            // 点击处理
            setOnClickListener {
                resetOptionsBackground()
                background = ContextCompat.getDrawable(context, R.drawable.option_selected_bg)
                selectedOption = index
                radioButtons[index].isChecked = true  // trigger radio button
            }
        }.also { addView(it) } // 使用also确保添加视图
    }

    // 复位选项的背景
    private fun resetOptionsBackground() {
        val context = binding.root.context
        (0 until binding.options.childCount).forEach { i ->
            binding.options.getChildAt(i).background =
                ContextCompat.getDrawable(context, R.drawable.option_default_bg)
        }
    }

    fun Int.dpToPx(): Int = (this * Resources.getSystem().displayMetrics.density).toInt()

    // 处理选择题
    @SuppressLint("SetTextI18n")
    private fun handleChoiceQuestion(question: Question): List<String> {
        return extractOptions(question.content)?.let { (stem, options) ->
            binding.question.text = "${question.questionIdx}.$stem"
            addOptions(options)
        } ?: run {
            binding.question.text = "${question.questionIdx}.${question.content}"
            listOf("A", "B", "C", "D")
        }
    }

    // 处理判断题
    @SuppressLint("SetTextI18n")
    private fun handleJudgeQuestion(question: Question): List<String> {
        binding.question.text = "${question.questionIdx}.${question.content}"
        return listOf("对", "错")
    }

    // 渲染选项按钮
    private fun renderOptionsButton(options: List<String>) {
        radioButtons.clear()  // reset 1

        options.forEach { text ->
            RadioButton(requireContext()).apply {
                id = View.generateViewId()
                this.text = text
                layoutParams = RadioGroup.LayoutParams(
                    WRAP_CONTENT, WRAP_CONTENT
                ).apply {
                    marginStart = resources.getDimensionPixelSize(R.dimen.radio_spacing)
                }
                binding.rgAnswer.addView(this)
                radioButtons.add(this)  // 对应option text 和 radio button
            }
        }
    }

    private fun handleQuestionError(e: Exception) {
        binding.run {
            question.text = "加载题目出错"
            btnNextQuestion.isEnabled = false
        }
        Log.e("QuestionFragment", "取题错误", e)
    }

    // 进度条回调函数
    private fun SeekBar.onProgressChangedWithCallback(
        onProgressChanged: (Int) -> Unit = {},
        onProgressEnd: (Int) -> Unit
    ) {
        setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
            override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
                // 只有当用户拖动时才处理
                if (fromUser) {
                    if (progress != lastProgress) {
                        onProgressChanged(progress)
                        lastProgress = progress
                    }
                }
                //
            }

            override fun onStartTrackingTouch(seekBar: SeekBar) {}
            override fun onStopTrackingTouch(seekBar: SeekBar) {
                onProgressEnd(seekBar.progress)
            }
        })
    }

    fun EditText.onTextChangedWithCallback(
        onTextChanged: (String) -> Unit = {},
        onTextEnd: (String) -> Unit
    ) {
        addTextChangedListener(object : TextWatcher {
            override fun afterTextChanged(s: Editable?) {
                s?.toString()?.let {
                    onTextChanged(it)
                    onTextEnd(it)
                }
            }

            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
        })
    }


//
}


